package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}

    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进入公共字段的填充...");
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AutoFill autoFillAnnotation = method.getAnnotation(AutoFill.class);
        Long loginUserId = BaseContext.getCurrentId();
        if(null != autoFillAnnotation){
            Object[] args = joinPoint.getArgs();
            if(Objects.nonNull(args)){
                for (Object arg : args) {
                    Class<?> argClass = arg.getClass();
                    log.info("参数类型为：{}",argClass.getName());
                    String packageName = argClass.getPackageName();
                    log.info("参数所在的包为：{}",packageName);
                    if(Objects.equals(packageName, "com.sky.entity")){
                        PropertyDescriptor createTime = BeanUtils.getPropertyDescriptor(argClass, "createTime");
                        PropertyDescriptor updateTime = BeanUtils.getPropertyDescriptor(argClass, "updateTime");
                        PropertyDescriptor createUser = BeanUtils.getPropertyDescriptor(argClass, "createUser");
                        PropertyDescriptor updateUser = BeanUtils.getPropertyDescriptor(argClass, "updateUser");

                        OperationType operationType = autoFillAnnotation.value();
                        LocalDateTime now = LocalDateTime.now();
                        switch (operationType){
                            case INSERT:
                                try {
                                    log.info("填充createTime, createUser...");
                                    createTime.getWriteMethod().invoke(arg, now);
                                    createUser.getWriteMethod().invoke(arg,loginUserId);
                                } catch (IllegalAccessException e) {
                                    throw new RuntimeException(e);
                                } catch (InvocationTargetException e) {
                                    throw new RuntimeException(e);
                                }
                            case UPDATE:
                                try {
                                    log.info("填充updateTime, updateUser...");
                                    updateTime.getWriteMethod().invoke(arg,now);
                                    updateUser.getWriteMethod().invoke(arg,loginUserId);
                                } catch (IllegalAccessException e) {
                                    throw new RuntimeException(e);
                                } catch (InvocationTargetException e) {
                                    throw new RuntimeException(e);
                                }
                        }
                    }
                }
            }
        }
    }


}
